using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Design;
using Microsoft.Xna.Framework.Graphics;
using WODPL.Models;

namespace WODPL.GameComponents
{
    public class Character : DrawableGameComponent
    {
        private readonly CharacterModel characterModel;
        private readonly GameCamera camera;
        private readonly BasicEffect effect;
        private VertexBuffer vertexBuffer;
        private IndexBuffer indexBuffer;
        private readonly VertexPositionNormalTexture[] data = new[] {
            new VertexPositionNormalTexture(new Vector3(-1,0,-1), Vector3.Normalize(new Vector3(-1,0,-1)), Vector2.Zero), 
            new VertexPositionNormalTexture(new Vector3(1,0,-1), Vector3.Normalize(new Vector3(1,0,-1)), Vector2.Zero), 
            new VertexPositionNormalTexture(new Vector3(1,0,1), Vector3.Normalize(new Vector3(1,0,1)), Vector2.Zero), 
            new VertexPositionNormalTexture(new Vector3(-1,0,1), Vector3.Normalize(new Vector3(-1,0,1)), Vector2.Zero), 
            new VertexPositionNormalTexture(new Vector3(-1,2,-1), Vector3.Normalize(new Vector3(-1,2,-1)), Vector2.Zero), 
            new VertexPositionNormalTexture(new Vector3(1,2,-1), Vector3.Normalize(new Vector3(1,2,-1)), Vector2.Zero), 
            new VertexPositionNormalTexture(new Vector3(1,2,1), Vector3.Normalize(new Vector3(1,2,1)), Vector2.Zero), 
            new VertexPositionNormalTexture(new Vector3(-1,2,1), Vector3.Normalize(new Vector3(-1,2,1)), Vector2.Zero)};
        private readonly short[] indexData = new short[]
                                                      {
                                                          0,1,2, 0,2,3, 
                                                          4,5,6, 4,6,7, 
                                                          0,3,7, 0,4,7,
                                                          0,1,5, 0,4,5,
                                                          1,2,6, 1,5,6,
                                                          2,6,7, 2,3,7
                                                      };

        public Character(Game game, GameCamera camera, CharacterModel characterModel) : base(game)
        {
            this.camera = camera;
            this.characterModel = characterModel;
            effect = new BasicEffect(game.GraphicsDevice, null)
                         {
                             DiffuseColor = new Vector3(1,0,1)
                         };
            effect.EnableDefaultLighting();
            vertexBuffer = new VertexBuffer(game.GraphicsDevice, VertexPositionNormalTexture.SizeInBytes * data.Length, BufferUsage.None);
            vertexBuffer.SetData(data);
            indexBuffer = new IndexBuffer(game.GraphicsDevice, sizeof (short)*indexData.Length, BufferUsage.None, IndexElementSize.SixteenBits);
            indexBuffer.SetData(indexData);
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
            GraphicsDevice.RenderState.DepthBufferEnable = true;
            GraphicsDevice.VertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionNormalTexture.VertexElements);
            effect.World = Matrix.CreateScale(10,20,10) * Matrix.CreateTranslation(characterModel.Origin);
            effect.View = camera.ViewMatrix;
            effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, (float)GraphicsDevice.Viewport.Width / GraphicsDevice.Viewport.Height,
                                                         1.0f, 500);
            GraphicsDevice.RenderState.CullMode = CullMode.None;
            GraphicsDevice.RenderState.FillMode = FillMode.Solid;
            effect.Begin();
            foreach (var pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
                GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, data, 0, data.Length, indexData, 0, indexData.Length/3);
                pass.End();
            }
            effect.End();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
            characterModel.Update(gameTime);
        }
    }
}